home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095.zip / RDOFF / LDRDF.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  20KB  |  727 lines

  1. /* ldrdf.c    RDOFF Object File linker/loader main program
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  */
  8.  
  9. /* TODO: Make the system skip a module (other than the first) if none
  10.  * of the other specified modules contain a reference to it.
  11.  * May require the system to make an extra pass of the modules to be
  12.  * loaded eliminating those that aren't required.
  13.  *
  14.  * Support all the existing documented options...
  15.  *
  16.  * Support libaries (.a files - requires a 'ranlib' type utility)
  17.  *        (I think I've got this working, so I've upped the version)
  18.  *
  19.  * -s option to strip resolved symbols from exports. (Could make this an
  20.  * external utility)
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include "nasm.h"
  28. #include "rdoff.h"
  29. #include "nasmlib.h"
  30. #include "symtab.h"
  31. #include "collectn.h"
  32. #include "rdlib.h"
  33.  
  34. #define LDRDF_VERSION "0.30"
  35.  
  36. /* global variables - those to set options: */
  37.  
  38. int     verbose = 0;    /* reflects setting of command line switch */
  39. int    align = 16;
  40. int    errors = 0;    /* set by functions to cause halt after current
  41.                stage of processing */
  42.  
  43. /* the linked list of modules that must be loaded & linked */
  44.  
  45. struct modulenode {
  46.     rdffile    f;    /* the file */
  47.     long    coderel;    /* module's code relocation factor */
  48.     long    datarel;    /* module's data relocation factor */
  49.     long    bssrel;        /* module's bss data reloc. factor */
  50.     void *    header;        /* header location, if loaded */
  51.     char *    name;        /* filename */
  52.     struct modulenode *next;
  53. };
  54.  
  55. #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
  56. #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
  57.  
  58.  
  59. struct modulenode *modules = NULL,*lastmodule = NULL;
  60.  
  61. /* the linked list of libraries to be searched for missing imported
  62.    symbols */
  63.  
  64. struct librarynode * libraries = NULL, * lastlib = NULL;
  65.  
  66. void *symtab;    /* The symbol table */
  67.  
  68. rdf_headerbuf * newheader ;    /* New header to be written to output */
  69.  
  70. /* loadmodule - find the characteristics of a module and add it to the
  71.  *        list of those being linked together            */
  72.  
  73. void loadmodule(char *filename)
  74. {
  75.   struct modulenode *prev;
  76.   if (! modules) {
  77.     modules = malloc(sizeof(struct modulenode));
  78.     lastmodule = modules;
  79.     prev = NULL;
  80.   }
  81.   else {
  82.     lastmodule->next = malloc(sizeof(struct modulenode));
  83.     prev = lastmodule;
  84.     lastmodule = lastmodule->next;
  85.   }
  86.  
  87.   if (! lastmodule) {
  88.     fputs("ldrdf: not enough memory\n",stderr);
  89.     exit(1);
  90.   }
  91.  
  92.   if (rdfopen(&lastmodule->f,filename)) {
  93.     rdfperror("ldrdf",filename);
  94.     exit(1);
  95.   }
  96.  
  97.   lastmodule->header = NULL;    /* header hasn't been loaded */
  98.   lastmodule->name = filename;
  99.   lastmodule->next = NULL;
  100.  
  101.   if (prev) {
  102.     lastmodule->coderel = prev->coderel + prev->f.code_len;
  103.     if (lastmodule->coderel % align != 0)
  104.       lastmodule->coderel += align - (lastmodule->coderel % align);
  105.     lastmodule->datarel = prev->datarel + prev->f.data_len;
  106.     if (lastmodule->datarel % align != 0)
  107.       lastmodule->datarel += align - (lastmodule->datarel % align);
  108.   }
  109.   else {
  110.     lastmodule->coderel = 0;
  111.     lastmodule->datarel = 0;
  112.   }
  113.  
  114.   if (verbose)
  115.     printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
  116.        lastmodule->coderel,lastmodule->f.code_len,
  117.        lastmodule->datarel,lastmodule->f.data_len);
  118.  
  119.   lastmodule->header = malloc(lastmodule->f.header_len);
  120.   if (!lastmodule->header) {
  121.       fprintf(stderr,"ldrdf: out of memory\n");
  122.       exit(1);
  123.   }
  124.  
  125.   if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
  126.   {
  127.       rdfperror("ldrdf",filename);
  128.       exit(1);
  129.   }
  130. }
  131.  
  132. /* load_library        add a library to list of libraries to search
  133.  *                      for undefined symbols
  134.  */
  135.  
  136. void load_library(char * name)
  137. {
  138.     if (verbose)
  139.     printf("adding library %s to search path\n",name);
  140.     
  141.     if (! lastlib) {
  142.     lastlib = libraries = malloc(sizeof(struct librarynode));
  143.     }
  144.     else
  145.     {
  146.     lastlib->next = malloc(sizeof(struct librarynode));
  147.     lastlib = lastlib->next;
  148.     }
  149.  
  150.     if (! lastlib) {
  151.     fprintf(stderr, "ldrdf: out of memory\n");
  152.     exit(1);
  153.     }
  154.     strcpy (lastlib->name = malloc (1+strlen(name)), name);
  155.     lastlib->fp = NULL;
  156.     lastlib->referenced = 0;
  157.     lastlib->next = NULL;
  158. }
  159.  
  160.  
  161. /* build_symbols()    step through each module's header, and locate
  162.  *            exported symbols, placing them in a global table
  163.  */
  164.  
  165. long bsslength;
  166.  
  167. void mod_addsymbols(struct modulenode * mod)
  168. {
  169.     rdfheaderrec *r;
  170.     symtabEnt e;
  171.     long cbBss;
  172.  
  173.     mod->bssrel = bsslength;
  174.     cbBss = 0;
  175.     rdfheaderrewind(&mod->f);
  176.     while ((r = rdfgetheaderrec(&mod->f)))
  177.     {
  178.  
  179.     if (r->type == 5)        /* Allocate BSS */
  180.         cbBss += r->b.amount;
  181.  
  182.     if (r->type != 3) continue;    /* ignore all but export recs */
  183.  
  184.     e.segment = r->e.segment;
  185.     e.offset = r->e.offset + 
  186.         (e.segment == 0 ? mod->coderel : /* 0 -> code */
  187.          e.segment == 1 ? mod->datarel : /* 1 -> data */
  188.          mod->bssrel) ; /* 2 -> bss  */
  189.     
  190.     e.flags = 0;
  191.     e.name = malloc(strlen(r->e.label) + 1);
  192.     if (! e.name)
  193.     {
  194.         fprintf(stderr,"ldrdf: out of memory\n");
  195.         exit(1);
  196.     }
  197.     strcpy(e.name,r->e.label);
  198.     symtabInsert(symtab,&e);
  199.     }
  200.     bsslength += cbBss;
  201. }
  202.  
  203. void build_symbols()
  204. {
  205.   struct modulenode *mod;
  206.  
  207.   if (verbose) printf("building global symbol table:\n");
  208.   newheader = rdfnewheader();
  209.  
  210.   symtab = symtabNew();
  211.   bsslength = 0;          /* keep track of location of BSS symbols */
  212.  
  213.   for (mod = modules; mod; mod = mod->next)
  214.   {
  215.       mod_addsymbols( mod );
  216.   }
  217.   if (verbose)
  218.   {
  219.       symtabDump(symtab,stdout);
  220.       printf("BSS length = %ld bytes\n\n",bsslength);
  221.   }
  222. }
  223.  
  224.  
  225. /* scan_libraries()    search through headers of modules for undefined
  226.  *            symbols, and scan libraries for those symbols,
  227.  *            adding library modules found to list of modules
  228.  *            to load.                    */
  229.  
  230. void scan_libraries(void)
  231. {
  232.     struct modulenode     * mod, * nm;
  233.     struct librarynode    * lib;
  234.     rdfheaderrec    * r;
  235.     int            found;
  236.     char        * tmp;
  237.  
  238.     if (verbose) printf("Scanning libraries for unresolved symbols...\n");
  239.  
  240.     mod = modules;
  241.  
  242.     while (mod)
  243.     {
  244.     rdfheaderrewind(&mod->f);
  245.  
  246.     while ((r = rdfgetheaderrec(&mod->f)))
  247.     {
  248.         if (r->type != 2) continue;    /* not an import record */
  249.         if ( symtabFind (symtab,r->i.label) )
  250.         continue;        /* symbol already defined */
  251.         
  252.         /* okay, we have an undefined symbol... step through
  253.            the libraries now */
  254.         if (verbose >= 2) {
  255.         printf("undefined symbol '%s'...",r->i.label);
  256.         fflush(stdout);
  257.         }
  258.  
  259.         lib = libraries;
  260.         found = 0;
  261.  
  262.         tmp = newstr(r->i.label);
  263.         while (! found && lib)
  264.         {
  265.         /* move this to an outer loop...! */
  266.         nm = malloc(sizeof(struct modulenode));
  267.  
  268.         if (rdl_searchlib(lib,tmp,&nm->f))
  269.         {    /* found a module in the library */
  270.  
  271.             /* create a modulenode for it */
  272.  
  273.             if (! nm) {
  274.             fprintf(stderr,"ldrdf: out of memory\n");
  275.             exit(1);
  276.             }
  277.  
  278.             nm->name = newstrcat(lib->name,nm->f.name);
  279.             if (verbose >= 2) printf("found in '%s'\n",nm->name);
  280.  
  281.             nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
  282.             if (nm->coderel % align != 0)
  283.             nm->coderel += align - (nm->coderel % align);
  284.  
  285.             nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
  286.             if (nm->datarel % align != 0)
  287.             nm->datarel += align - (nm->datarel % align);
  288.  
  289.             nm->header = malloc(nm->f.header_len);
  290.             if (! nm->header)
  291.             {
  292.             fprintf(stderr,"ldrdf: out of memory\n");
  293.             exit(1);
  294.             }
  295.  
  296.             if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
  297.             {
  298.             rdfperror("ldrdf",nm->name);
  299.             exit(1);
  300.             }
  301.  
  302.             nm->next = NULL;
  303.             found = 1;
  304.             lastmodule->next = nm;
  305.             lastmodule = nm;
  306.  
  307.             if (verbose)
  308.             printf("%s code = %08lx (+%04lx), data = %08lx "
  309.                    "(+%04lx)\n",lastmodule->name,
  310.                    lastmodule->coderel,lastmodule->f.code_len,
  311.                    lastmodule->datarel,lastmodule->f.data_len);
  312.  
  313.             /* add the module's info to the symbol table */
  314.             mod_addsymbols(nm);
  315.         }
  316.         else
  317.         {
  318.             if (rdl_error) {
  319.             rdl_perror("ldrdf",lib->name);
  320.             exit(1);
  321.             }
  322.             free(nm);
  323.         }
  324.         lib = lib->next;
  325.         }
  326.         free(tmp);
  327.         if (!found && verbose >= 2) printf("not found\n");
  328.     }
  329.     mod = mod->next;
  330.     }
  331. }
  332.  
  333. /* load_segments()    allocates memory for & loads the code & data segs
  334.  *            from the RDF modules
  335.  */
  336.  
  337. char *text,*data;
  338. long textlength,datalength;
  339.  
  340. void load_segments(void)
  341. {
  342.   struct modulenode *mod;
  343.  
  344.   if (!modules) {
  345.     fprintf(stderr,"ldrdf: nothing to do\n");
  346.     exit(0);
  347.   }
  348.   if (!lastmodule) {
  349.     fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
  350.     exit(3);
  351.   }
  352.  
  353.   if (verbose)
  354.     printf("loading modules into memory\n");
  355.  
  356.   /* The following stops 16 bit DOS from crashing whilst attempting to
  357.      work using segments > 64K */
  358.   if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
  359.                 platforms... */
  360.     if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
  361.     lastmodule->datarel + lastmodule->f.data_len > 65535) {
  362.       fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
  363.           "version.\nldrdf: code size = %05lx, data size = %05lx\n",
  364.           lastmodule->coderel + lastmodule->f.code_len,
  365.           lastmodule->datarel + lastmodule->f.data_len);
  366.       exit(1);
  367.     }
  368.   }
  369.  
  370.   text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
  371.   data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
  372.  
  373.   if (!text || !data) {
  374.     fprintf(stderr,"ldrdf: out of memory\n");
  375.     exit(1);
  376.   }
  377.  
  378.   mod = modules;
  379.   while (mod) {        /* load the segments for each module */
  380.       if (verbose >= 2) printf("  loading %s\n",mod->name);
  381.       if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
  382.       rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
  383.       rdfperror("ldrdf",mod->name);
  384.       exit(1);
  385.       }
  386.       rdfclose(&mod->f);    /* close file; segments remain */
  387.       mod = mod->next;
  388.   }
  389. }
  390.     
  391. /* link_segments()    step through relocation records in each module's
  392.  *            header, fixing up references.
  393.  */
  394.  
  395. void link_segments(void)
  396. {
  397.   struct modulenode    *mod;
  398.   Collection        imports;
  399.   symtabEnt        *s;
  400.   long             rel,relto;
  401.   char             *seg;
  402.   rdfheaderrec        *r;
  403.   int            bRelative;
  404.  
  405.   if (verbose) printf("linking segments\n");
  406.  
  407.   collection_init(&imports);
  408.  
  409.   for (mod = modules; mod; mod = mod->next) {
  410.     if (verbose >= 2) printf("* processing %s\n",mod->name);
  411.     rdfheaderrewind(&mod->f);
  412.     while((r = rdfgetheaderrec(&mod->f))) {
  413.     if (verbose >= 3) printf("record type: %d\n",r->type);
  414.     switch(r->type) {
  415.     case 1:        /* relocation record */
  416.         if (r->r.segment >= 64) {         /* Relative relocation; */
  417.         bRelative = 1;        /* need to find location relative */
  418.         r->r.segment -= 64;        /* to start of this segment */
  419.         relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
  420.         }
  421.         else
  422.         bRelative = 0;        /* non-relative - need to relocate
  423.                      * at load time            */
  424.  
  425.         /* calculate absolute offset of reference, not rel to beginning of
  426.            segment */
  427.         r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
  428.  
  429.         /* calculate the relocation factor to apply to the operand -
  430.            the base address of one of this modules segments if referred
  431.            segment is 0 - 2, or the address of an imported symbol
  432.            otherwise. */
  433.  
  434.         if (r->r.refseg == 0) rel = mod->coderel;
  435.         else if (r->r.refseg == 1) rel = mod->datarel;
  436.         else if (r->r.refseg == 2) rel = mod->bssrel;
  437.         else {        /* cross module link - find reference */
  438.         s = *colln(&imports,r->r.refseg - 2);
  439.         if (!s) {
  440.             fprintf(stderr,"ldrdf: link to undefined segment %04x in"
  441.                 " %s:%d\n", r->r.refseg,mod->name,r->r.segment);
  442.             errors = 1;
  443.             break;
  444.         }
  445.         rel = s->offset;
  446.       
  447.         r->r.refseg = s->segment;    /* change referred segment, 
  448.                            so that new header is
  449.                            correct */
  450.         }
  451.  
  452.         if (bRelative)    /* Relative - subtract current segment start */
  453.         rel -= relto; 
  454.         else  
  455.         {            /* Add new relocation header */
  456.         rdfaddheader(newheader,r);
  457.         }
  458.         
  459.         /* Work out which segment we're making changes to ... */
  460.         if (r->r.segment == 0) seg = text;
  461.         else if (r->r.segment == 1) seg = data;
  462.         else {
  463.         fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
  464.             "%s\n", r->r.segment,mod->name);
  465.         errors = 1;
  466.         break;
  467.         }
  468.  
  469.         /* Add the relocation factor to the datum specified: */
  470.  
  471.         if (verbose >= 3)
  472.         printf("  - relocating %d:%08lx by %08lx\n",r->r.segment,
  473.                r->r.offset,rel);
  474.  
  475.         /**** The following code is non-portable. Rewrite it... ****/
  476.         switch(r->r.length) {
  477.         case 1:
  478.         seg[r->r.offset] += (char) rel;
  479.         break;
  480.         case 2:
  481.         *(int16 *)(seg + r->r.offset) += (int16) rel;
  482.         break;
  483.         case 4:
  484.         *(long *)(seg + r->r.offset) += rel;
  485.         break;
  486.         }
  487.         break;
  488.  
  489.     case 2:        /* import record */
  490.         s = symtabFind(symtab, r->i.label);
  491.         if (s == NULL) {
  492.         /* Need to add support for dynamic linkage */
  493.         fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
  494.             r->i.label,mod->name);
  495.         errors = 1;
  496.         }
  497.         else 
  498.         {
  499.         *colln(&imports,r->i.segment - 2) = s;
  500.         if (verbose >= 2)
  501.             printf("imported %s as %04x\n", r->i.label, r->i.segment);
  502.         }
  503.         break;
  504.  
  505.     case 3:        /* export; dump to output new version */
  506.         s = symtabFind(symtab, r->e.label);
  507.         if (! s) {
  508.         fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
  509.             "exported in header of '%s'\n",r->e.label,mod->name);
  510.         continue;
  511.         }
  512.         r->e.offset = s->offset;
  513.         rdfaddheader(newheader,r);
  514.         break;
  515.  
  516.     case 4:        /* DLL record */
  517.         rdfaddheader(newheader,r);        /* copy straight to output */
  518.         break;
  519.     }
  520.     }
  521.     if (rdf_errno != 0) {
  522.     rdfperror("ldrdf",mod->name);
  523.     exit(1);
  524.     }
  525.     collection_reset(&imports);
  526.   }
  527. }
  528.     
  529. /* write_output()    write linked program out to a file */
  530.  
  531. void write_output(char *filename)
  532. {
  533.     FILE        * fp;
  534.     rdfheaderrec    r;
  535.  
  536.     if (verbose) printf("writing output to '%s'\n",filename);
  537.  
  538.     fp = fopen(filename,"wb");
  539.     if (! fp)
  540.     {
  541.     fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
  542.     exit(1);
  543.     }
  544.   
  545.     
  546.     /* add BSS length count to header... */
  547.     if (bsslength)
  548.     {
  549.     r.type = 5;
  550.     r.b.amount = bsslength;
  551.     rdfaddheader(newheader,&r);
  552.     }
  553.  
  554.     /* Write header */
  555.     rdfwriteheader(fp,newheader);
  556.     rdfdoneheader(newheader);
  557.     newheader = NULL;
  558.  
  559.     /* Write text */
  560.     if (fwrite(&textlength,1,4,fp) != 4
  561.     || fwrite(text,1,textlength,fp) !=textlength)
  562.     {
  563.     fprintf(stderr,"ldrdf: error writing %s\n",filename);
  564.     exit(1);
  565.     }
  566.  
  567.     /* Write data */
  568.     if (fwrite(&datalength,1,4,fp) != 4 ||
  569.     fwrite(data,1,datalength,fp) != datalength)
  570.     {
  571.     fprintf (stderr,"ldrdf: error writing %s\n", filename);
  572.     exit(1);
  573.     }
  574.     fclose(fp);
  575. }
  576.  
  577.  
  578. /* main program: interpret command line, and pass parameters on to
  579.  * individual module loaders & the linker
  580.  *
  581.  * Command line format:
  582.  * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
  583.  *
  584.  * Default action is to output a file named 'aout.rdx'. -x specifies
  585.  * that the linked object program should be executed, rather than
  586.  * written to a file. -r specifies that the object program should
  587.  * be prelocated at address 'xxxx'. This option cannot be used
  588.  * in conjunction with -x.
  589.  */
  590.  
  591. const char *usagemsg = "usage:\n"
  592. " ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
  593. "       [-l<libname> ...]\n\n"
  594. " ldrdf -h    displays this message\n"
  595. " ldrdf -r    displays version information\n\n"
  596. "   -o selects output filename (default is aout.rdx)\n"
  597. "   -x causes ldrdx to link & execute rather than write to file\n"
  598. "   -a x causes object program to be statically relocated to address 'x'\n"
  599. "   -v turns on verbose mode\n"
  600. "   -p x causes segments to be aligned (padded) to x byte boundaries\n"
  601. "      (default is 16 bytes)\n"
  602. "   -l<name> causes 'name' to be linked in as a library. Note no search is\n"
  603. "      performed - the entire pathname MUST be specified.\n";
  604.  
  605. void usage(void)
  606. {
  607.   fputs(usagemsg,stderr);
  608. }
  609.  
  610. int main(int argc,char **argv)
  611. {
  612.   char    *ofilename = "aout.rdx";
  613.   long    relocateaddr = -1;    /* -1 if no relocation is to occur */
  614.   int    execute = 0;        /* 1 to execute after linking, 0 otherwise */
  615.   int    procsw = 1;        /* set to 0 by '--' */
  616.   int    tmp;
  617.  
  618.   if (argc == 1) {
  619.     usage();
  620.     exit(1);
  621.   }
  622.  
  623.   /* process command line switches, and add modules specified to linked list
  624.      of modules, keeping track of total memory required to load them */
  625.  
  626.   while(argv++,--argc) {
  627.     if (procsw && !strcmp(*argv,"-h")) {    /* Help command */
  628.       usage(); exit(1);
  629.     }
  630.     else if (procsw && !strcmp(*argv,"-r")) {
  631.       printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
  632.          sizeof(int) == 2 ? "16 bit" : "32 bit");
  633.       exit(1);
  634.     }
  635.     else if (procsw && !strcmp(*argv,"-o")) {
  636.       ofilename = *++argv;
  637.       --argc;
  638.       if (execute) {
  639.     fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
  640.     exit(1);
  641.       }
  642.       if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
  643.     }
  644.     else if (procsw && !strcmp(*argv,"-x")) {
  645.       execute++;
  646.       if (verbose > 1) printf("will execute linked object\n");
  647.     }
  648.     else if (procsw && !strcmp(*argv,"-a")) {
  649.       relocateaddr = readnum(*++argv,&tmp);
  650.       --argc;
  651.       if (tmp) {
  652.     fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
  653.         *argv);
  654.     exit(1);
  655.       }
  656.       if (execute) {
  657.     fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
  658.     exit(1);
  659.       }
  660.       if (verbose) printf("will relocate to %08lx\n",relocateaddr);
  661.     }
  662.     else if (procsw && !strcmp(*argv,"-v")) {
  663.       verbose++;
  664.       if (verbose == 1) printf("verbose mode selected\n");
  665.     }
  666.     else if (procsw && !strcmp(*argv,"-p")) {
  667.       align = readnum(*++argv,&tmp);
  668.       --argc;
  669.       if (tmp) {
  670.     fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
  671.         *argv);
  672.     exit(1);
  673.       }
  674.       if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
  675.       && align != 32 && align != 256) {
  676.     fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
  677.         "1,2,4,8,16 or 256\n",align);
  678.     exit(1);
  679.       }
  680.       if (verbose > 1) printf("alignment %d selected\n",align);
  681.     }
  682.     else if (procsw && !strncmp(*argv,"-l",2)) {
  683.     load_library(*argv + 2);
  684.     }
  685.     else if (procsw && !strcmp(*argv,"--")) {
  686.       procsw = 0;
  687.     }
  688.     else {                    /* is a filename */
  689.       if (verbose > 1) printf("processing module %s\n",*argv);
  690.       loadmodule(*argv);
  691.     }
  692.   }
  693.  
  694.   /* we should be scanning for unresolved references, and removing
  695.      unreferenced modules from the list of modules here, so that
  696.      we know about the final size once libraries have been linked in */
  697.  
  698.   build_symbols();    /* build a global symbol table...           */
  699.  
  700.   scan_libraries();    /* check for imported symbols not in table,
  701.                and ensure the relevant library modules
  702.                are loaded */
  703.  
  704.   load_segments();    /* having calculated size of reqd segments, load
  705.                each rdoff module's segments into memory */
  706.  
  707.   link_segments();    /* step through each module's header, and resolve
  708.                references to the global symbol table.
  709.                This also does local address fixups. */
  710.  
  711.   if (errors) {
  712.     fprintf(stderr,"ldrdf: there were errors - aborted\n");
  713.     exit(errors);
  714.   }
  715.   if (execute) {
  716.     fprintf(stderr,"ldrdf: module execution not yet supported\n");
  717.     exit(1);
  718.   }
  719.   if (relocateaddr != -1) {
  720.     fprintf(stderr,"ldrdf: static relocation not yet supported\n");
  721.     exit(1);
  722.   }
  723.  
  724.   write_output(ofilename);
  725.   return 0;
  726. }
  727.